﻿using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.SQS;
using Amazon.SQS.Model;
using Attribute = Amazon.SQS.Model.Attribute;

namespace ShuttleBus.Transports.AmazonSqs
{
    internal class Sqs : ISqs
    {
        private readonly AmazonSQS _sqsClient;
        private readonly int _timeToProcessMessage;
        private readonly IDictionary<string, string> _queues;

        public IEndpoint Endpoint { get; set; }

        public Sqs(AmazonSQS sqsClient, IEndpoint endpoint, int timeToProcessMessage)
        {
            Endpoint = endpoint;
            _sqsClient = sqsClient;
            _timeToProcessMessage = timeToProcessMessage;
            _queues = new Dictionary<string, string>();
        }

        public void Dispose()
        {
            _sqsClient.Dispose();
        }

        public void Send(object message, Uri location)
        {
            if(message == null || location == null)
            {
                return;
            }

            var sendRequest = new SendMessageRequest()
                .WithMessageBody(message.ToString())
                .WithQueueUrl(CreateOrVerifyQueue(location.Host));
            _sqsClient.SendMessage(sendRequest);
        }

        public bool HasMessage(out BaseMessage message)
        {
            var queueUrl = CreateOrVerifyQueue(Endpoint.Path);

            var request = new ReceiveMessageRequest
            {
                QueueUrl = queueUrl,
                VisibilityTimeout = _timeToProcessMessage,
                MaxNumberOfMessages = 1,
                AttributeName = new List<string> { "ApproximateReceiveCount" }
            };
            var response = _sqsClient.ReceiveMessage(request);
            if (response.ReceiveMessageResult.Message.Count == 1)
            {
                var recievedMessage = response.ReceiveMessageResult.Message[0];
                message = new SqsMessage(recievedMessage);
                return true;
            }
            message = null;
            return false;
        }

        private string CreateOrVerifyQueue(string queueName)
        {
            if (!_queues.ContainsKey(queueName))
            {
                var request = new CreateQueueRequest { QueueName = queueName };
                var response = _sqsClient.CreateQueue(request);
                _queues[queueName] = response.CreateQueueResult.QueueUrl;
                var attributesRequest = new SetQueueAttributesRequest();
                attributesRequest.Attribute = new List<Attribute>() { new Attribute() { Name = "MaximumMessageSize", Value = "65536" } };
                attributesRequest.QueueUrl = response.CreateQueueResult.QueueUrl;
                _sqsClient.SetQueueAttributes(attributesRequest);
            }
            return _queues[queueName];
        }

        public void RemoveMessage(BaseMessage message)
        {
            if (message != null)
            {
                var deleteMessageRequest = new DeleteMessageRequest()
                    .WithReceiptHandle(message.Id)
                    .WithQueueUrl(CreateOrVerifyQueue(Endpoint.Path));

                _sqsClient.DeleteMessage(deleteMessageRequest);
            }
        }
    }
}